
require("Scripts/Common/Utility")
require("Scripts/Common/Class")
require("Scripts/Common/Json")

TextureManager = Class()

function TextureManager:Ctor()
	-- 已经注册好的纹理信息
	self._loaded_atlas = {}
	-- 用于反射查找
	self._name_map_path = {}
--[[ 以下注释中带*号的表示json文件必须填充的对象
	{
	"file_path1":  -- 文件路径
		{
		"resource": 1,	-- 加载完毕后系统生成
		"width": 100,	-- 图片的宽*
		"height":100,	-- 图片的高*
		"map":	-- 子图片映射*
			{ -- 子图片名称*：{"x":子图片左上角x坐标*, "y":子图片左上角y坐标*, "w":子图片的宽度*, "h":子图片的高度*, "t":top的纹理坐标, "b":bottom的纹理坐标, "l":left的纹理坐标, "r":right的纹理坐标}
			"buttonskinup":{"x":20, "y":20, "w":30, "h":40, "t":0, "b":0, "l":0, "r":0},
			"buttonskindown":{"x":20, "y":20, "w":30, "h":40, "t":0, "b":0, "l":0, "r":0}
			}
		},
	"file_path2"...
	}
--]]
	-- 正在加载中的纹理信息
	self._loading_atlas = {}
--[[
	{
	"file_path1":
		{
		"name": [object1, object2, object3]		
		},
	"file_path2"...
	}
--]]
end

function TextureManager:LoadJsonFile(path)
	-- 打开文件
	local file = io.open(path, "r")
	-- 判断文件是否打开成功
	if file == nil then Global_Log(path.."load failed") end
	-- 读取全部的文件内容	
	local content = file:read("*a")
	-- 关闭文件
	file:close()
	-- 将文件内容，json decode
	content = Json.decode(content)
	-- 将图片信息载入
	for k, v in pairs(content) do
		self._loaded_atlas[k] = v
	end
end

-- 获取纹理信息，path：图片资源的路径，name：子图片的名字
function TextureManager:GetTextureInfo(path, name)
	-- 获取加载完毕的图片信息
	local loaded_atlas = self._loaded_atlas[path]
	-- 如果没有，则返回空
	if loaded_atlas == nil then return nil end
	-- 如果有，则获取map字段信息
	local loaded_subatlas = loaded_atlas.map
	-- 如果没有map字段信息，则返回空
	if loaded_subatlas == nil then return nil end
	-- 返回子图片信息
	return loaded_subatlas[name]
end

-- 根据图片名字查找纹理信息
function TextureManager:GetTexturePath(name)
	local path = self._name_map_path[name]
	if path then return path end
	for k, v in pairs(self._loaded_atlas) do
		if v.map[name] then
			self._name_map_path[name] = k
			return k
		end
	end
	return nil
end

-- 设置纹理图片，path：图片资源路径，name：子图片名字，object：show对象
function TextureManager:SetTexture(path, name, object)
	-- 检查path是否为空
	if path == nil then path = self:GetTexturePath(name) end
	-- 获取加载完毕的图片信息
	local loaded_atlas = self._loaded_atlas[path]
	-- 如果有，则设置show的纹理和纹理坐标
	if loaded_atlas and loaded_atlas.resource then
		loaded_subatlas = loaded_atlas.map[name]
		if loaded_subatlas == nil then return end
		object:SetTexture(loaded_atlas.resource)
		object:SetTextureCoord(loaded_subatlas.t, loaded_subatlas.b, loaded_subatlas.l, loaded_subatlas.r)
		return
	end
	-- 获取正在加载的图片信息
	local loading_atlas = self._loading_atlas[path]
	-- 如果已经正在加载，则添加到正在加载的队列中
	if loading_atlas then
		local object_map = loading_atlas[name]
		if object_map == nil then
			object_map = {}
			loading_atlas[name] = object_map
		end
		object_map[object] = object
		return
	end
	-- 如果还没有正在加载，那么就构建一个正在加载信息，在添加到队列中
	local new_object_map = {}
	new_object_map[object] = object
	local new_loading_atlas = {}	
	new_loading_atlas[name] = new_object_map
	self._loading_atlas[path] = new_loading_atlas
	-- 通知异步加载资源
	Global_UISystem:CreateTexture(path)
end

-- 添加纹理，path：图片资源路径，resource：纹理资源
function TextureManager:AddTexture(path, resource)
	-- 将信息保存到加载完毕的信息中
	local loaded_atlas = self._loaded_atlas[path]
	if loaded_atlas == nil then
		Global_Log("unknow path:"..path)
		return
	end
	loaded_atlas.resource = resource
	-- 计算纹理坐标
	for k, v in pairs(loaded_atlas.map) do
		if v.t == nil then v.t = v.y / loaded_atlas.height end
		if v.b == nil then v.b = (v.y + v.h) / loaded_atlas.height end
		if v.l == nil then v.l = v.x / loaded_atlas.width end
		if v.r == nil then v.r = (v.x + v.w) / loaded_atlas.width end
	end
	-- 获取正在加载的信息，将等待中的show对象一一设置纹理
	local loading_atlas = self._loading_atlas[path]
	if loading_atlas == nil then return end
	for k, v in pairs(loading_atlas) do
		local loaded_subatlas = loaded_atlas.map[k]
		if loaded_subatlas then
			for object_k, object_v in pairs(v) do
				object_v:SetTexture(resource)
				object_v:SetTextureCoord(loaded_subatlas.t, loaded_subatlas.b, loaded_subatlas.l, loaded_subatlas.r)
			end
		else
			Global_Log("unknow name:"..k)
		end
	end
	-- 清空等待该纹理对象的show
	self._loading_atlas[path] = nil
end

-- 清空纹理资源
function TextureManager:Clear()
	for k, v in pairs(self._loaded_atlas) do
		Global_UISystem:ReleaseTexture(v.resource)
	end
	self._loaded_atlas = {}
	self._loading_atlas = {}
end

g_TextureManager = TextureManager()

function Global_AddTexture(path, resource)
	g_TextureManager:AddTexture(path, resource)
end

